﻿using System;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Media.Imaging;
using System.Windows.Controls.Primitives;

namespace EasySL.Controls
{   
    public class ExCommandPanel : ContentControl
    {
        private bool? isAscend;
        public bool? IsAscend
        {
            get
            {
                return isAscend;
            }
            set
            {
                isAscend = value;

                if (this.sortStateImage == null)
                    return;

                if (value == null)
                {
                    this.sortStateImage.Visibility = Visibility.Collapsed;

                    if (this.sortImage != null)
                        this.SetImage(this.sortImage, "button_arrowdown.png");
                }
                else
                {
                    this.sortStateImage.Visibility = Visibility.Visible;

                    if (value == true)
                    {
                        this.SetImage(this.sortStateImage, "button_arrowup_mark.png");

                        if (this.sortImage != null)
                            this.SetImage(this.sortImage, "button_arrowdown.png");
                    }
                    else
                    {
                        this.SetImage(this.sortStateImage, "button_arrowdown_mark.png");

                        if (this.sortImage != null)
                            this.SetImage(this.sortImage, "button_arrowup.png");
                    }
                }
            }
        }

        public bool IsFilter
        {
            set
            {
                if (value)
                    this.filterStateImage.Visibility = Visibility.Visible;
                else
                    this.filterStateImage.Visibility = Visibility.Collapsed;
            }
        }
        
        public string BindProperty { get; set; }

        public Action<string, bool> OnSort { get; set; }
        public Action<string> OnFilter { get; set; }
        public Action<string> OnDelete { get; set; }
        public Action<string, bool> OnExpand { get; set; }
        public ExFilterType FilterType { get; set; }

        public ExCommandPanel()
            : base()
        {
            this.DefaultStyleKey = typeof(ExCommandPanel);
            this.Loaded += new RoutedEventHandler(ExCommandPanel_Loaded);
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            this.statePanel = this.GetTemplateChild("statePanel") as Panel;
            this.commandPanel = this.GetTemplateChild("commandPanel") as Panel;

            this.commandPanel.Opacity = 0;
            this.commandPanel.MouseEnter += (s, e) =>
            {
                this.Show();
            };
            this.commandPanel.MouseLeave += (s, e) =>
            {
                this.Hide();
            };

            this.expandPanel = this.GetTemplateChild("expandPanel") as Panel;
            this.expandPanel.Visibility = Visibility.Collapsed;
            
        }

        public void SetEnableExpand()
        {
            this.expandPanel.Visibility = Visibility.Visible;
            var expandImage = GetImage("button_expand.png");
            expandImage.Tag = false;
            expandImage.MouseLeftButtonDown += (s, e) =>
            {
                if ((bool)expandImage.Tag)
                    this.SetImage(expandImage, "button_expand.png");
                else
                    this.SetImage(expandImage, "button_collapse.png");

                expandImage.Tag = !(bool)expandImage.Tag;
                if (this.OnExpand != null)
                    this.OnExpand(this.BindProperty, (bool)expandImage.Tag);
            };
            this.expandPanel.Children.Add(expandImage);
        }
        
        public void SetEnableFilter()
        {         
            this.filterImage = GetImage("icon_filter.png");
            this.filterImage.MouseLeftButtonDown += (s, e) =>
            {
                //Filter();
                ShowFilterMenu(e);
            };

            this.commandPanel.Children.Add(this.filterImage);

            this.filterStateImage = GetImage("icon_filter_mark.png");
            this.filterStateImage.Visibility = Visibility.Collapsed;
            this.statePanel.Children.Add(this.filterStateImage);
        }

        public void SetEnableSort()
        {
            this.sortStateImage = GetImage("button_arrowdown_mark.png");
            this.IsAscend = null;
            this.statePanel.Children.Add(this.sortStateImage);
                       
            this.sortImage = GetImage("button_arrowdown.png");

            this.sortImage.MouseLeftButtonDown += (s, e) =>
            {
                this.IsAscend = !(this.IsAscend ?? true);
                Sort();             
            };

            this.commandPanel.Children.Add(this.sortImage); 
        }

        public void SetEnableDelete()
        {
            this.deleteImage = GetImage("button_del.png");

            this.commandPanel.Children.Add(this.deleteImage);
         
            this.deleteImage.MouseLeftButtonDown += (s, e) =>
            {
                e.Handled = true;
                Delete();
            };          
        }

        private void ShowFilterMenu(MouseButtonEventArgs e)
        {
            Panel panel = this.filterMenuPopup.Parent as Panel;
            if (panel != null)
            {
                filterMenuPopup.VerticalOffset = e.GetPosition(panel).Y - 5;
                filterMenuPopup.HorizontalOffset = e.GetPosition(panel).X - 5;
                filterMenuPopup.IsOpen = true;

                var exFilterMenu = filterMenuPopup.Child as ExFilterMenu;
                exFilterMenu.BindProperty = this.BindProperty;
                exFilterMenu.MouseLeave += new MouseEventHandler(filterMenuPopup_MouseLeave);

                if (this.FilterType == ExFilterType.Number)
                    FillNumberMenus(exFilterMenu);
                else if (this.FilterType == ExFilterType.String)
                    FillStringMenus(exFilterMenu);     
            }
        }

        private void FillNumberMenus(ExFilterMenu exFilterMenu)
        {
            exFilterMenu.ClearItems();

            exFilterMenu.AddMenuItem("Equals...", ExFilterAction.Equals);
            exFilterMenu.AddMenuItem("Does Not Equal...", ExFilterAction.NotEquals);

            exFilterMenu.AddSplitItem();

            exFilterMenu.AddMenuItem("Greater Than...", ExFilterAction.GreaterThan);
            exFilterMenu.AddMenuItem("Less Than...", ExFilterAction.LessThan);
            exFilterMenu.AddMenuItem("Between...", ExFilterAction.Between);

            exFilterMenu.AddSplitItem();
            exFilterMenu.AddMenuItem("Top 10", ExFilterAction.Top10);
            exFilterMenu.AddMenuItem("Above Average", ExFilterAction.AboveAverage);
            exFilterMenu.AddMenuItem("Below Average", ExFilterAction.BelowAverage);

            exFilterMenu.AddSplitItem();
            exFilterMenu.AddMenuItem("Clear Filter", ExFilterAction.Clear);
        }

        private void FillStringMenus(ExFilterMenu exFilterMenu)
        {
            exFilterMenu.ClearItems();

            exFilterMenu.AddMenuItem("Equals...", ExFilterAction.Equals);
            exFilterMenu.AddMenuItem("Does Not Equal...", ExFilterAction.NotEquals);

            exFilterMenu.AddSplitItem();

            exFilterMenu.AddMenuItem("Begins With...", ExFilterAction.BeginWith);
            exFilterMenu.AddMenuItem("Ends With...", ExFilterAction.EndWith);

            exFilterMenu.AddSplitItem();

            exFilterMenu.AddMenuItem("Contains...", ExFilterAction.Contains);
            exFilterMenu.AddMenuItem("Does Not Contain...", ExFilterAction.NotContains);

            exFilterMenu.AddSplitItem();
            exFilterMenu.AddMenuItem("Clear Filter", ExFilterAction.Clear);
        }

        private Action<ExFilterAction> GetClickCallBack()
        {
            Action<ExFilterAction> onClick = action =>
            {
                ChildWindow filterPanel = new ExFilterPanel();
                filterPanel.Show();      
            };

            return onClick;
        }

        void filterMenuPopup_MouseLeave(object sender, MouseEventArgs e)
        {
            this.filterMenuPopup.IsOpen = false;
            this.Hide();
        }

        private void Sort()
        {         
            if (this.OnSort != null)
                this.OnSort(this.BindProperty, this.IsAscend ?? false);
        }

        private void Filter()
        {
            if (this.OnFilter != null)
                this.OnFilter(this.BindProperty);
        }

        private void Delete()
        {            
            if (this.OnDelete != null)
                this.OnDelete(this.BindProperty);
        } 

        private void ExCommandPanel_Loaded(object sender, RoutedEventArgs e)
        {
            FrameworkElement element = this;

            while (element != null && !(element is ExDataGrid))
                element = VisualTreeHelper.GetParent(element) as FrameworkElement;

            if (element is ExDataGrid)
            {
                var dg = element as ExDataGrid;

                this.filterMenuPopup = dg.FilterMenuPopup;

                foreach (ExDataGridColumn c in dg.Columns)
                {
                    if (c != null && object.Equals(c.Header, this.Content))
                    {
                        if (c is ExDataGridCheckBoxColumn)
                        {
                            this.Visibility = Visibility.Collapsed;
                            return;
                        }
                        
                        this.BindProperty = c.BindProperty;
                        this.FilterType = c.FilterType;
                        dg.AddCommandPanel(this);

                        this.statePanel.Children.Clear();
                        this.commandPanel.Children.Clear();

                        if (c.EnableFilter)
                            this.SetEnableFilter();

                        if (c.EnableSort)
                            this.SetEnableSort();

                        if (c.EnableDelete)
                            this.SetEnableDelete();

                        if (c.EnableExpand)
                            this.SetEnableExpand();

                        if (dg.SortProperty == c.BindProperty)
                            this.IsAscend = dg.IsAscend;
                    }
                }
            }
        }

        private Image GetImage(string imageName)
        {
            Image image = new Image();
            SetImage(image, imageName);
            return image;
        }

        private void SetImage(Image image, string imageName)
        {
            image.Stretch = Stretch.None;
            image.Source = new BitmapImage(new Uri(imagePath + imageName, UriKind.RelativeOrAbsolute));
        }

        private void Show()
        {
            (this.commandPanel.Resources["show"] as Storyboard).Begin();
        }

        private void Hide()
        {
            (this.commandPanel.Resources["hide"] as Storyboard).Begin();
        }

        private readonly string imagePath = "/EasySL.Controls;component/Images/";
        private Panel statePanel;
        private Panel commandPanel;
        private Panel expandPanel;

        private Image sortImage;
        private Image sortStateImage;

        private Image filterImage;
        private Image filterStateImage;

        private Image deleteImage;

        private Popup filterMenuPopup;
    }
}
